package rdbms;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import DAO.DatabasePool;
import DAO.ENSequenceDAO;


import model.ENSequence;

public class RDBMSENSequenceDAO implements ENSequenceDAO {
	
	private String selectSequence =
		"select (sequence_value+1) as value " +
		" from EN_SEQUENCE where sequence_id = ? for update";

	private String updateSequence =
		"update EN_SEQUENCE set sequence_value = ? where sequence_id = ?";
	
	private String restoreSequence = 
		"update EN_SEQUENCE set sequence_value = 0";
	
	private String idConnection;
	
	public RDBMSENSequenceDAO(final String idConnection) throws SQLException {
		this.idConnection = idConnection;
	}
	
	private int getNextVal(final int type) throws Exception {
		Connection conn = null;
		PreparedStatement pstInsert = null;
		ResultSet rssInsert = null;
		PreparedStatement pstUpdate = null;
		ResultSet rssUpdate = null;
		int value = -1;
		try {
			conn = DatabasePool.getConnection(idConnection);

			pstInsert = conn.prepareStatement(selectSequence);
			pstInsert.setInt(1, type);
			rssInsert = pstInsert.executeQuery();
			rssInsert.next();
			value = rssInsert.getInt(1);
			
			pstUpdate = conn.prepareStatement(updateSequence);
			pstUpdate.setInt(1, value);
			pstUpdate.setInt(2, type);
			pstUpdate.executeUpdate();
			
		} catch (final SQLException e) {
			e.printStackTrace();
			throw new SQLException(e.getMessage()+". Exception while retrieving sequence number "+type+".",
					e.getCause().getMessage());
		} finally {
			if (rssInsert != null) rssInsert.close();
			if (pstInsert != null) pstInsert.close();
			if (rssUpdate != null) rssUpdate.close();
			if (pstUpdate != null) pstUpdate.close();
		}
		return value;
	}
	
	public int nextval(ENSequence sequence) throws Exception {
		switch (sequence) {
			case CLASS_ID : {
				ENSequence.CLASS_ID.setValue(getNextVal(1)); 
				return ENSequence.CLASS_ID.currentValue();
			}	
			case CONCEPT_ID : {
				ENSequence.CONCEPT_ID.setValue(getNextVal(2));
				return ENSequence.CONCEPT_ID.currentValue();
			}
			case CONCEPT_DOMAIN_ID : {
				ENSequence.CONCEPT_DOMAIN_ID.setValue(getNextVal(3));
				return ENSequence.CONCEPT_DOMAIN_ID.currentValue();
			}
			case RELATION_ID : {
				ENSequence.RELATION_ID.setValue(getNextVal(4));
				return ENSequence.RELATION_ID.currentValue();
			}
			case DOMAIN_ID : {
				ENSequence.DOMAIN_ID.setValue(getNextVal(5));
				return ENSequence.DOMAIN_ID.currentValue();
			}
			case TERM_ID : {
				ENSequence.TERM_ID.setValue(getNextVal(6));
				return ENSequence.TERM_ID.currentValue();
			}
			case DATE_ID : {
				ENSequence.DATE_ID.setValue(getNextVal(7));
				return ENSequence.DATE_ID.currentValue();
			}
		}
		return -1;
	}
	
	public void restore() throws Exception {
		Connection conn = null;
		PreparedStatement pst = null;
		try {
			conn = DatabasePool.getConnection(idConnection);
			pst = conn.prepareStatement(restoreSequence);
			pst.execute();
		} catch (final SQLException e) {
			e.printStackTrace();
			throw new SQLException(e.getMessage()+
					". Exception while restoring sequence values.",
					e.getCause().getMessage());
		} finally {
			if (pst != null) pst.close();
		}
	}

	public String getSelectSequence() {
		return selectSequence;
	}

	public void setSelectSequence(String selectSequence) {
		this.selectSequence = selectSequence;
	}

	//public int nextval(ENSequence sequence)
		//	throws Exception {
		// TODO Auto-generated method stub
		//return 0;
//	}
}

